﻿using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;

namespace WorkflowFramework
{
    public class WorkFlowExecutor : IWorkFlowExecutor
    {
        protected readonly List<IFlowStep> _steps;
        private int _currentStepIndex = -1;
        private bool _isPaused;
        private bool _isCompleted;
        private string _currentFailedStep = string.Empty;
        private readonly object _lock = new();

        public bool IsPaused => _isPaused;
        public bool IsCompleted => _isCompleted;
        public string CurrentFailedStep => _currentFailedStep;

        List<IFlowStep> IWorkFlowExecutor.Steps => _steps;

        public WorkFlowExecutor(List<IFlowStep> steps)
        {
            _steps = steps.ToList();
        }

        public async Task ExecuteFlowAsync(CancellationToken cancellationToken = default)
        {
            if (_steps.Count == 0)
            {
                _isCompleted = true;
                return;
            }

            _currentStepIndex = 0;

            while (_currentStepIndex < _steps.Count && !_isCompleted)
            {
                var step = _steps[_currentStepIndex];
                //判断工作流是否被暂停
                while (_isPaused && !_isCompleted && !cancellationToken.IsCancellationRequested)
                {
                    await Task.Delay(100, cancellationToken);
                }

                try
                {
                    await step.InitializeAsync();
                    await step.PreProcessAsync();
                    await step.ExecuteAsync();
                    await step.PostProcessAsync();

                    _currentStepIndex++;
                }
                catch (Exception ex)
                {
                    Log.Information($"Step [{step.StepName}] failed: {ex.Message}");
                    lock (_lock)
                    {
                        _currentFailedStep = step.StepName;
                        _isPaused = true;
                    }

                    // 等待用户指令
                    while (_isPaused && !_isCompleted && !cancellationToken.IsCancellationRequested)
                    {
                        await Task.Delay(100, cancellationToken);
                    }

                    if (_isCompleted || cancellationToken.IsCancellationRequested)
                    {
                        break;
                    }
                }
            }

            if (_currentStepIndex >= _steps.Count)
            {
                _isCompleted = true;
                Log.Information($"Flow execution completed successfully.");
            }
        }

        public async Task ProcessUserCommandAsync(WorkFlowCommand command, CancellationToken cancellationToken = default)
        {
            lock (_lock)
            {
                if (!_isPaused)
                {
                    if (command.Equals(WorkFlowCommand.Pause))
                    {
                        _isPaused = true;
                        return;
                    }
                    else
                    {
                        throw new InvalidOperationException("Flow is not in paused state.");
                    }
                }
                switch (command)
                {
                    case WorkFlowCommand.Continue:
                        _isPaused = false;
                        _currentFailedStep = string.Empty;
                        _currentStepIndex++; // 跳过当前失败步骤
                        break;
                    case WorkFlowCommand.Retry:
                        _isPaused = false;
                        _currentFailedStep = string.Empty;
                        // 保持_currentStepIndex不变，下次会重试当前步骤
                        break;
                    case WorkFlowCommand.Terminate:
                        _isPaused = false;
                        _isCompleted = true;
                        break;
                    default:
                        throw new ArgumentOutOfRangeException(nameof(command), command, null);
                }
            }

            await Task.CompletedTask;
        }
    }
}
